<?php

class rdbms_viewer {

    private $dsn    =   false;  // core viewer DSN
    private $dbh    =   false;
    private $dsns   =   false;
     public $dbhs   =   array();
     public $errors =   array();
    
    
    function __construct($options) {
        foreach($options as $attribute => $value) {
            if(isset($this->$attribute)) {
                $this->$attribute   =   $value;
            }
        }
      
        if($this->dsns) {
            foreach($this->dsns as $dsn) {
                $this->set_database_handle($dsn);
            }
        }

    }
    
    function __destruct() {
        if($this->dbh) {
            $this->dbh->disconnect();
        }
        
        if($this->dbhs) {
            foreach($this->dbhs as $dbh) {
                $dbh->disconnect();
            }
        }
    }
    
    function data_factory($type, $factory_options = array()) {
        
        switch($type) {
            default:
                require_once('lib/generic_data.class.php');
                $factory    =   new generic_data($factory_options);
        }
        
        return $factory;
    }
    
    private function append_error_message($message) {
        $this->errors[] =   $message;
    }
    
    private function get_error_messages() {
        if(count($this->errors) > 0) {
            var_dump($this->errors);
        }
    }
    
    /** set_dbh
    *
    *   Connects to a database and sets $dbh / handler for MDB2 functionality.
    *
    *   Multiple instances to a database resource can be used when specifying 
    *   a prefix.  
    *
    *   In the future I may push this functionality into an array space but if
    *   you want this now, please extend this class and create a new attribute
    *   for it.
    *
    *   @param str
    *   @access private
    *   @return none
    *   @author david_yerrington@yahoo.com
    */
    function set_database_handle($dsn, $target_dbh_obj = false) {
        require_once 'MDB2.php';
        
        $dbhs_prefix    =   $dsn['username'].'@'.$dsn['hostspec'];
        
        $this->dbhs[$dbhs_prefix]   =&  MDB2::factory($dsn);
        $this->dbhs[$dbhs_prefix]->loadModule('Extended', null, false);
        $this->dbhs[$dbhs_prefix]->loadModule('Manager');
        $this->dbhs[$dbhs_prefix]->loadModule('Reverse');
        $this->dbhs[$dbhs_prefix]->setFetchMode(MDB2_FETCHMODE_ASSOC);
        
        if (PEAR::isError($this->dbhs[$dbhs_prefix])) {
            $this->append_error_message($this->dbhs[$dbhs_prefix]->getMessage());
        }
        
    }
    
    function set_mdb_query_tool() {
        require_once 'MDB/QueryTool.php';
        
    }
    
    /** get_databases()
    *
    *   Returns array of database resources associated with active database handler.
    *   This is just a wrapper for MDB listDatabases() for now.
    *
    *   @access public
    *   @return array
    *   @author david_yerrington@yahoo.com
    */
    function get_databases($dbhs_prefix = false) {
        if($dbhs_prefix) {
            return $this->dbhs[$dbhs_prefix]->listDatabases();
        }
        return $this->dbh->listDatabases();
    }

    /** get_tables()
    *
    *   Returns array of database table resources associated with active database handler.
    *   This is just a wrapper for MDB listDatabases() for now.
    *
    *   @access public
    *   @param  string
    *   @return array
    *   @author david_yerrington@yahoo.com
    */
    function get_tables($dbhs_prefix, $database = '') {
        if(strlen($database) < 1 || !is_string($database)) {
            $this->append_error_message('Cannot get tables for database name: '.$database);
        }
        return $this->dbhs[$dbhs_prefix]->listTables($database);
    }
    
    /** get_table_info()
    *
    *   Returns array of database table resources associated with active database handler.
    *   This is just a wrapper for MDB listDatabases() for now.
    *
    *   @access public
    *   @param  string
    *   @return array
    *   @author david_yerrington@yahoo.com
    */
    function get_table_info($table) {
        if(strlen($table) < 1 || !is_string($table)) {
            $this->append_error_message('Cannot get table info for table: '.$table);
        }
        return $this->dbh->tableInfo($table);        
    }
    
    /** get_data_from_table()
    *
    *   Calls generic data class that dynamically builds SQL for a given database
    *   platform and translates the results as a nice multi-dimensional array.
    *
    *   This was created to provided a generic insight to "what's in that table!?"
    *
    *   TODO: Abstract pagination / hooks
    *
    *   @access public
    *   @param  mixed dsn, str, array
    *   @return array
    *   @author david_yerrington@yahoo.com
    */
    function get_data_from_table($dsn, $table, $primary_key = '') {
        $generic_data_options   =   array('dsn' => $dsn);
        $generic_data   =   $this->data_factory('generic_data', $generic_data_options);
        $generic_data->set_querytool_attributes($table, $primary_key);
        return $generic_data->getAll();
    }

    /** fetch_dsn
    *
    *   Fetch dsn's from rdbms core schema.  If $dsn_id is present, this method
    *   will return a flattened array of the cooresponding DSN or if it isn't
    *   provided, this method will return all available DSN's 
    *
    *   @access public (this might change)
    *   @param int
    *   @return array
    *   @uses class::generic_data, PEAR::MDB_QueryTool
    *   @author david_yerrington@yahoo.com
    */
    function fetch_dsn($dsn_id = false) {
        $generic_data_options   =   array('dsn' => $this->dsns['rdbms_viewer']);
        $rdbms  =   $this->data_factory('generic_data', $generic_data_options);
        $rdbms->set_querytool_attributes('rdbms_dsn', 'dsn_id');
        $rdbms->reset();
        if($dsn_id) {
            $result = $rdbms->get($dsn_id);
        } else {
            $result =   $rdbms->getAll();
        }
        return $result;
    }

}
